package com.george.order.loadbalance;


import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @title: WeightedLeastConnectionsLoadBalancer.java
 * @description: 负载均衡算法-加权最少连接数（Weighted Least Connections）
 * @author: George.Dong
 * @date: 2024/5/30 12:17
 */
public class WeightedLeastConnectionsLoadBalancer {
    /**
     * 服务器列表，其中包含每个服务器的权重信息
     */
    private List<WeightServer> servers;
    /**
     * 服务器连接数映射，记录每个服务器当前的连接数
     */
    private Map<WeightServer, Integer> serverConnections;

    /**
     * 构造函数，初始化服务器列表和连接数。
     *
     * @param servers 服务器列表，每个服务器包含名称和权重。
     */
    public WeightedLeastConnectionsLoadBalancer(List<WeightServer> servers) {
        this.servers = servers;
        this.serverConnections = new HashMap<>();
        // 初始化每个服务器的连接数为0
        for (WeightServer server : servers) {
            serverConnections.put(server, 0);
        }
    }

    /**
     * 获取下一个服务器，基于加权最小连接数算法。
     *
     * @return 返回下一个应被分配的服务器。
     */
    public synchronized WeightServer getNextServer() {
        WeightServer leastConnectedServer = null;
        double minConnections = Double.MAX_VALUE;
        // 遍历服务器列表，计算加权连接数，找到当前连接数最少的服务器
        for (WeightServer server : servers) {
            double effectiveConnections = (double) serverConnections.get(server) / server.getWeight();
            if (effectiveConnections < minConnections) {
                minConnections = effectiveConnections;
                leastConnectedServer = server;
            }
        }
        // 为选中的服务器增加一个连接
        serverConnections.put(leastConnectedServer, serverConnections.get(leastConnectedServer) + 1);
        return leastConnectedServer;
    }


    public static void main(String[] args) {
        // 初始化服务器列表
        List<WeightServer> servers = Arrays.asList(
                new WeightServer("Server1", 5),
                new WeightServer("Server2", 2),
                new WeightServer("Server3", 3)
        );
        // 创建负载均衡器实例
        WeightedLeastConnectionsLoadBalancer lb = new WeightedLeastConnectionsLoadBalancer(servers);

        // 模拟分配服务器的过程
        for (int i = 0; i < 10; i++) {
            WeightServer server = lb.getNextServer();
            String clientIp = "192.168.0.13" + i;
            System.out.println("Client IP: " + clientIp + " -> Server: " + server.getName());
        }
    }

}
